#include <stdio.h>
#include <time.h>
#include <tgmath.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>

#define NIT_SHORT_NAMES
#include <nit/socket.h>

#include "tp.h"

#define SEC_TO_NANO 1e9 /* billion */

static size_t
next_utf8(const char *str)
{
	char c = *str;
	size_t len = 0;

	for (; c >> 7; ++len, c = c << 1);

	if (!len)
		return 1;

	return len;
}

static size_t
utf8_size(const char *str, int units, size_t rest)
{
	size_t len = 0;
	size_t unit_size;

	for (; units && rest; --units, rest -= unit_size, len += unit_size)
		unit_size = next_utf8(str + len);

	return len;
}

int
t3_tp(Nit_joint *in, Nit_joint *out, T3_tpad *ad, T3_tpre *re)
{
	const char *pos = ad->bytes;
	size_t size = ad->size;
	size_t chunk_size;
	struct timespec timer = {
		.tv_sec = trunc(ad->spc),
		.tv_nsec = SEC_TO_NANO * (ad->spc - trunc(ad->spc))
	};

	for (; size; pos += chunk_size, size -= chunk_size) {
		if (re && in && joint_ready(in)) {
			re->done = 0;
			re->amt = pos - ad->bytes;
			return 1;
		}

		chunk_size = utf8_size(pos, ad->chunk, size);

		if (!joint_send(out, pos, chunk_size))
			return 0;

		if (nanosleep(&timer, NULL) < 0)
			return 0;
	}

	if (re)
		re->done = 1;

	return 1;
}
